package ru.papergames.view.components.field
{
	import flash.display.Graphics;
	import flash.display.Shape;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.geom.Rectangle;
	import ru.papergames.model.vo.PositionVO;
	import ru.papergames.view.events.PositionSelectEvent;
	
	import mx.core.UIComponent;

	public class FightFieldGrid extends UIComponent
	{
		public static const CELL_WIDTH:uint = 28;
		public static const CELL_HEIGHT:uint = 28;	
			
					
		
		//rows
		private var _rows:int = 5;		
		public function get rows():uint {
			return _rows;
		} 
		
		public function set rows(val:uint):void {
			_rows = val;
			this.invalidateDisplayList();
			this.invalidateSize();
		}
		
		//cols
		private var _cols:int = 5;		
		public function get cols():uint {
			return _cols;
		} 
		
		public function set cols(val:uint):void {
			_cols = val;
			this.invalidateDisplayList();
			this.invalidateSize();
		}
		
		//inverted
		private var _inverted:Boolean = false;		
		public function get inverted():Boolean {
			return _inverted;
		} 
		
		public function set inverted(val:Boolean):void {
			_inverted = val;
			this.invalidateDisplayList();
		}
		
		//selection_enabled
		private var _selection_enabled:Boolean = false;		
		public function get selection_enabled():Boolean {
			return _selection_enabled;
		} 
		
		public function set selection_enabled(val:Boolean):void {
			_selection_enabled = val;
			_selector.visible = _selection_enabled;
			
			this.invalidateDisplayList();
		}
		
		//selection_position
		private var _selection_position:PositionVO = new PositionVO();		
		public function get selection_position():PositionVO {
			return _selection_position;
		} 
		
		public function set selection_position(val:PositionVO):void {
			
			if (!val) {
				_selector.visible = false;
				return;
			}
			
			var pos:PositionVO = checkPosition(val.x, val.y);
			
			var changed:Boolean = !_selector.visible || _selection_position.x != pos.x || _selection_position.y != pos.y;
			
			if (!changed) return;
			
			//trace('NEW POS: ' + pos.toString());
			
			_selection_position = pos;
			if (_selector) {
				_selection_position.x = Math.min(cols-1, _selection_position.x);
				_selection_position.y = Math.min(rows-1, _selection_position.y);
							
				_selector.x = Math.min(cols-1, val.x)*x_step;
				_selector.y = Math.min(val.y, rows-1)*y_step;
			}
			
			_selector.visible = _selection_enabled;
			
			this.dispatchEvent(new PositionSelectEvent(PositionSelectEvent.AIM_CHANGED, _selection_position));
		}
		
		
		public var blockedCells:Array;		
		
		public var actors:ActorsHolder;
		
		private var _grid:Shape;
		private var _click_bg:Shape;
		private var _attack_area:Shape;
		private var _action_tokens:Sprite;
		private var _selector:PlaceSelector;		
		
		public function FightFieldGrid()
		{
			super();			
			this.addEventListener(MouseEvent.CLICK, onGridClick);			
			//this.addEventListener(PlaceSelector.DBL_CLICK, onGridDblClick, true);
			this.addEventListener(MouseEvent.MOUSE_MOVE, onGridMMove);
		}
		
		public function get x_step():Number {
			return CELL_WIDTH;
		}
		
		public function get y_step():Number {
			return CELL_HEIGHT;
		}
		
		public function emulateCellClick(pos:PositionVO):void {
			selection_position = pos;
			
			if ( !arrayContainsPos(blockedCells, selection_position.x, selection_position.y) ) {
				
				this.dispatchEvent(new PositionSelectEvent(PositionSelectEvent.SELECT, selection_position));
				
			}
		}
		
		private function onGridMMove(evt:MouseEvent):void {
			if (this.mouseX<0 || this.mouseY<0) {
				this.dispatchEvent(new MouseEvent(MouseEvent.ROLL_OUT));
				return;
			}
				
			selection_position = new PositionVO(Math.floor(this.mouseX/x_step), 
												Math.floor(this.mouseY/y_step));
		}
		
		private function onGridClick(evt:MouseEvent):void {
			if (!selection_enabled || this.mouseX<0 || this.mouseY<0) return;
			
			emulateCellClick( new PositionVO(	Math.floor(this.mouseX/x_step), 
												Math.floor(this.mouseY/y_step)) );
		}	
		
		private function onGridDblClick(evt:Event):void {
			if (!selection_enabled) return;
						
			this.dispatchEvent(new PositionSelectEvent(PositionSelectEvent.DBL_CLICK, selection_position));
		}
		
		override protected function createChildren():void {
			super.createChildren();			
								
			//click_bg
			_click_bg = new Shape();
			_click_bg.graphics.clear();
			_click_bg.graphics.beginFill(0xE8DCB0, 0.35);			
			_click_bg.graphics.drawRect(0, 0, 5, 5);			
			_click_bg.graphics.endFill();
			_click_bg.cacheAsBitmap = true;
						
			this.addChild(_click_bg);
			
			//grid
			_grid = new Shape();			
			this.addChild(_grid);
			_grid.cacheAsBitmap = true;
						
			//attack area
			_attack_area = new Shape();
			this.addChild(_attack_area);
			
			_action_tokens = new Sprite();
			this.addChild(_action_tokens);
						
			//selector
			_selector = new PlaceSelector();
			_selector.visible = false;
			this.addChild(_selector);
			
			actors = new ActorsHolder(x_step, y_step);
			this.addChild(actors);
		}
		
		override protected function commitProperties():void {
			super.commitProperties();
			
			
		}
		
		override protected function measure():void {
			super.measure();
			
			measuredWidth = x_step*cols;
        	measuredHeight = y_step*rows;
		}
		
		override protected function updateDisplayList(w:Number, h:Number):void {
			super.updateDisplayList(w, h);
			
			//click_bg
			_click_bg.width = x_step*cols;
			_click_bg.height = y_step*rows;
						
			var g:Graphics = _grid.graphics;
			
			g.clear();			
			g.lineStyle(1, 0x866F13, 0.5);
						
			//horizontals
			for (var i:int = 0; i <= rows; i++) {
				g.moveTo(0, i*y_step);
				g.lineTo(x_step*cols, i*y_step);
			}
			
			//verticals
			for (i = 0; i <= cols; i++) {
				g.moveTo(i*x_step, 0);
				g.lineTo(i*x_step, y_step*rows);
			}
			
			
			//selector
			_selector.width = x_step;
			_selector.height = y_step;		
			
			
		}
		
		public function toggleGrid():void {
			_grid.visible = !_grid.visible;
		}
		
		public function showAttackArea(center:PositionVO, distanceMin:uint = 1, distanceMax:uint = 1, enemiesPos:Array = null):void {
			clearAttackArea();
			
			center = checkPosition(center.x, center.y);
			
			function drawAreaCell(g:Graphics, rect:Rectangle):void {
								
				g.beginFill(0x866F13, 0.38);
				
				g.drawRect(rect.x + 2, rect.y + 2, rect.width - 4, rect.height - 4);
				
				g.endFill();
			}
			
			function drawActionToken(act_x:Number, act_y:Number):void {
				
			}
			
			for (var x_coord:int = center.x-distanceMax; x_coord <= center.x+distanceMax; x_coord++) {
				for (var y_coord:int = center.y-distanceMax; y_coord <= center.y+distanceMax; y_coord++) {
					
					if (x_coord < 0 || y_coord < 0 || 
						x_coord >= cols || y_coord >= rows ||
						( Math.max(Math.abs(x_coord-center.x), Math.abs(y_coord-center.y)) < distanceMin )	
										
					) continue;
					
					drawAreaCell( _attack_area.graphics, 
						new Rectangle(x_coord*x_step, y_coord*y_step, x_step, y_step) );
						
					var realCurPos:PositionVO = checkPosition(x_coord, y_coord);
					
					if ( enemiesPos && arrayContainsPos(enemiesPos, realCurPos.x, realCurPos.y) ) {
						drawActionToken(x_coord*x_step, y_coord*y_step);
					}
				}
			}
		}
		
		private function checkPosition(x_pos:uint, y_pos:uint):PositionVO {			
			return _inverted ? new PositionVO(cols - x_pos - 1, y_pos) : new PositionVO(x_pos, y_pos);
		}
		
		private function arrayContainsPos(arr:Array, x_pos:int, y_pos:int):Boolean {
			if (!arr) return false;
			
			for each (var p:PositionVO in arr) {
				if ( p.x == x_pos && p.y == y_pos ) return true;
			}
			
			return false;
		}
		
		public function clearAttackArea():void {
			_attack_area.graphics.clear();
			
			while (_action_tokens.numChildren > 0)
	        {
	        	_action_tokens.removeChildAt(0);
	        }
		}
		
	}
}